package com.tx.logsys.util;

import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import org.jinterop.dcom.core.*;
import org.jinterop.dcom.impls.JIObjectFactory;
import org.jinterop.dcom.impls.automation.IJIDispatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

@Component
//@ConfigurationProperties(prefix = "sv")
public class EventLogListener {

    private static Logger logger = LoggerFactory.getLogger(EventLogListener.class);

    private static final String WMI_DEFAULT_NAMESPACE = "ROOT\\CIMV2";

    // windows 配置信息
    private List<Map<String, String>> wins;

    public List<Map<String, String>> getWins() {
        return wins;
    }

    public void setWins(List<Map<String, String>> wins) {
        this.wins = wins;
    }

    private static List<Map<String, String>> wins_;

    @PostConstruct
    public void initWins() {
        wins_ = this.wins;
    }

    private static JISession configAndConnectDCom(String domain, String user,
                                                  String pass) throws Exception {
        JISystem.getLogger().setLevel(Level.OFF);
        try {
            JISystem.setInBuiltLogHandler(false);
        } catch (IOException ignored) {
            ;
        }
        JISystem.setAutoRegisteration(true);
        JISession dcomSession = JISession.createSession(domain, user, pass);
        dcomSession.useSessionSecurity(true);
        return dcomSession;
    }

    private static IJIDispatch getWmiLocator(String host, JISession dcomSession)
            throws Exception {
        JIComServer wbemLocatorComObj = new JIComServer(JIProgId
                .valueOf("WbemScripting.SWbemLocator"), host, dcomSession);
        return (IJIDispatch) JIObjectFactory.narrowObject(wbemLocatorComObj
                .createInstance().queryInterface(IJIDispatch.IID));
    }

    private static IJIDispatch toIDispatch(JIVariant comObjectAsVariant)
            throws JIException {
        return (IJIDispatch) JIObjectFactory.narrowObject(comObjectAsVariant
                .getObjectAsComObject());
    }

    /**
     * @return
     */
    public static String getLog() {
        StringBuffer sb = new StringBuffer();
        wins_.forEach(v -> {
            String domain = v.get("domain");
            String host = v.get("host");
            String user = v.get("user");
            String password = v.get("password");
            String res = getLog(domain, host, user, password);
            sb.append(res);
        });
        return sb.toString();
    }

    /**
     * @return
     */
    public static String getLog(int snum) {
        StringBuffer sb = new StringBuffer();

        Map<String, String> v = wins_.get(snum);

        String domain = v.get("domain");
        String host = v.get("host");
        String user = v.get("user");
        String password = v.get("password");

        String res = getLog(domain, host, user, password);
        sb.append(res);

        return sb.toString();
    }

    /**
     * @return
     */
    public static String getLog(String domain, String host, String user, String password) {

        logger.info("\n domain >>> {} \n host >>> {} \n user >>> {} \n password >>> {} \n ",domain, host, user, password);

        //if (args.length != 4) {
        //System.out.println("Usage: "
        //+ EventLogListener.class.getSimpleName()
        //+ " domain host username password");
        //return;
        //}

        // （domainName=远程计算机域名，hostIP=远程计算机IP地址,用户名=管理员级别的用户，密码=密码）
//        String domain = "";
//        String host = "192.168.1.118";
//        String user = "Administrator";
//        String password = "1";
        JISession dcomSession = null;
        try {
            // Connect to DCOM on the remote system, and create an instance of
            // the WbemScripting.SWbemLocator object to talk to WMI.
            dcomSession = configAndConnectDCom(domain, user, password);
            IJIDispatch wbemLocator = getWmiLocator(host, dcomSession);
            // Invoke the "ConnectServer" method on the SWbemLocator object via
            // it's IDispatch COM pointer. We will connect to
            // the default ROOT\CIMV2 namespace. This will result in us having a
            // reference to a "SWbemServices" object.
            JIVariant results[] = wbemLocator.callMethodA("ConnectServer",
                    new Object[]{new JIString(host),
                            new JIString(WMI_DEFAULT_NAMESPACE),
                            JIVariant.OPTIONAL_PARAM(),
                            JIVariant.OPTIONAL_PARAM(),
                            JIVariant.OPTIONAL_PARAM(),
                            JIVariant.OPTIONAL_PARAM(), new Integer(0),
                            JIVariant.OPTIONAL_PARAM()});
            IJIDispatch wbemServices = toIDispatch(results[0]);
            // Now that we have a SWbemServices DCOM object reference, we
            // prepare a WMI Query Language (WQL) request to be informed
            // whenever a
            // new instance of the "Win32_NTLogEvent" WMI class is created on
            // the remote host. This is submitted to the remote host via the
            // "ExecNotificationQuery" method on SWbemServices. This gives us
            // all events as they come in. Refer to WQL documentation to
            // learn how to restrict the query if you want a narrower focus.
//            final String QUERY_FOR_ALL_LOG_EVENTS = "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'";
            final String QUERY_FOR_ALL_LOG_EVENTS = "SELECT * FROM Win32_NTLogEvent WHERE Logfile = 'Application'";
            //final String QUERY_FOR_ALL_LOG_EVENTS = "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent' and TargetInstance.LogFile = 'System'";
            //Application
            //Security
            //System
            // and TargetInstance.LogFile = 'System'
            final int RETURN_IMMEDIATE = 16;
            final int FORWARD_ONLY = 32;
            JIVariant[] eventSourceSet = wbemServices.callMethodA(
                    "ExecNotificationQuery", new Object[]{
                            new JIString(QUERY_FOR_ALL_LOG_EVENTS),
                            new JIString("WQL"),
                            new JIVariant(new Integer(RETURN_IMMEDIATE
                                    + FORWARD_ONLY))});
            IJIDispatch wbemEventSource = (IJIDispatch) JIObjectFactory
                    .narrowObject((eventSourceSet[0]).getObjectAsComObject());
            // The result of the query is a SWbemEventSource object. This object
            // exposes a method that we can call in a loop to retrieve the
            // next Windows Event Log entry whenever it is created. This
            // "NextEvent" operation will block until we are given an event.
            // Note that you can specify timeouts, see the Microsoft
            // documentation for more details.
            boolean flag = true;
            int i = 0;
            while (flag) {
                flag = false;// 只执行一次
                // this blocks until an event log entry appears.
                JIVariant eventAsVariant = (JIVariant) (wbemEventSource
                        .callMethodA("NextEvent", new Object[]{JIVariant
                                .OPTIONAL_PARAM()}))[0];
                IJIDispatch wbemEvent = toIDispatch(eventAsVariant);
                // WMI gives us events as SWbemObject instances (a base class of
                // any WMI object). We know in our case we asked for a specific
                // object
                // type, so we will go ahead and invoke methods supported by
                // that Win32_NTLogEvent class via the wbemEvent IDispatch
                // pointer.
                // In this case, we simply call the "GetObjectText_" method that
                // returns us the entire object as a CIM formatted string. We
                // could,
                // however, ask the object for its property values via
                // wbemEvent.get("PropertyName"). See the j-interop
                // documentation and examples
                // for how to query COM properties.
                JIVariant objTextAsVariant = (JIVariant) (wbemEvent
                        .callMethodA("GetObjectText_",
                                new Object[]{new Integer(1)}))[0];
                String asText = objTextAsVariant.getObjectAsString()
                        .getString();
                System.out.println("******************************************==" + i++ + "==****************************");

                System.out.println(asText);

                return asText;

                //flag = false;

//				System.out.println("-----start------");
//				System.out.println(asText);
//				String[] texts = asText.split("\t");
//				for(int i = 0; i < texts.length; i++)
//				{
//		            System.out.println( "texts["+ i +"]= "+texts[i]);
//		        }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != dcomSession) {
                try {
                    JISession.destroySession(dcomSession);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return null;

    }

    public static void main(String[] args) {

        String domain = "";
        String host = "192.168.1.109";
        String user = "Administrator";
        String pass = "mzgs-5110";

//        String domain = "";
//        String host = "192.168.1.106";
//        String user = "aya77";
//        String pass = "177177";

        getLog(domain, host, user, pass);

    }
}
